package org.study.redis.api.util.jedis;

import com.google.common.collect.Lists;
import org.study.redis.api.util.ConvertUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.args.BitCountOption;
import redis.clients.jedis.args.BitOP;
import redis.clients.jedis.params.*;
import redis.clients.jedis.resps.LCSMatchResult;

import java.util.List;
import java.util.Map;

/**
 * Redis 操作工具类：String
 * 参考 {@link redis.clients.jedis.commands.StringCommands}
 *
 * @author doveylovey
 * @email 1135782208@qq.com
 * @date 2022年04月23日
 */
public class RedisStringUtils {
    private RedisStringUtils() {
        throw new AssertionError("不能实例化 RedisStringUtils 工具类");
    }

    public static String set(String key, String value) {
        String set = null;
        try (Jedis jedis = SysJedisPool.getResource()) {
            set = jedis.set(key, value);
        }
        return set;
    }

    public static String set(String key, String value, SetParams params) {
        String set = null;
        try (Jedis jedis = SysJedisPool.getResource()) {
            // TODO
            set = jedis.set(key, value, params);
        }
        return set;
    }

    public static long setnx(String key, String value) {
        long setnx;
        try (Jedis jedis = SysJedisPool.getResource()) {
            setnx = jedis.setnx(key, value);
        }
        return setnx;
    }

    public static String setex(String key, long seconds, String value) {
        String setex;
        try (Jedis jedis = SysJedisPool.getResource()) {
            setex = jedis.setex(key, seconds, value);
        }
        return setex;
    }

    public static String psetex(String key, long milliseconds, String value) {
        String psetex;
        try (Jedis jedis = SysJedisPool.getResource()) {
            psetex = jedis.psetex(key, milliseconds, value);
        }
        return psetex;
    }

    public static String get(String key) {
        String get;
        try (Jedis jedis = SysJedisPool.getResource()) {
            get = jedis.get(key);
        }
        return get;
    }

    public static String getDel(String key) {
        String getDel;
        try (Jedis jedis = SysJedisPool.getResource()) {
            getDel = jedis.getDel(key);
        }
        return getDel;
    }

    public static String getEx(String key, GetExParams params) {
        String getEx;
        try (Jedis jedis = SysJedisPool.getResource()) {
            getEx = jedis.getEx(key, params);
        }
        return getEx;
    }

    public static boolean setbit(String key, long offset, boolean value) {
        boolean setbit;
        try (Jedis jedis = SysJedisPool.getResource()) {
            setbit = jedis.setbit(key, offset, value);
        }
        return setbit;
    }

    public static boolean getbit(String key, long offset) {
        boolean getbit;
        try (Jedis jedis = SysJedisPool.getResource()) {
            getbit = jedis.getbit(key, offset);
        }
        return getbit;
    }

    public static long setrange(String key, long offset, String value) {
        long setrange;
        try (Jedis jedis = SysJedisPool.getResource()) {
            setrange = jedis.setrange(key, offset, value);
        }
        return setrange;
    }

    public static String getrange(String key, long startOffset, long endOffset) {
        String getrange;
        try (Jedis jedis = SysJedisPool.getResource()) {
            getrange = jedis.getrange(key, startOffset, endOffset);
        }
        return getrange;
    }

    public static String getSet(String key, String value) {
        String getSet;
        try (Jedis jedis = SysJedisPool.getResource()) {
            getSet = jedis.getSet(key, value);
        }
        return getSet;
    }

    public static List<String> mget(String... keys) {
        List<String> mget = Lists.newArrayList();
        try (Jedis jedis = SysJedisPool.getResource()) {
            mget = jedis.mget(keys);
        }
        return mget;
    }

    public static List<String> mget(List<String> keys) {
        List<String> mget = Lists.newArrayList();
        try (Jedis jedis = SysJedisPool.getResource()) {
            mget = jedis.mget(keys.toArray(new String[keys.size()]));
        }
        return mget;
    }

    public static String mset(String... keysvalues) {
        String mset;
        try (Jedis jedis = SysJedisPool.getResource()) {
            mset = jedis.mset(keysvalues);
        }
        return mset;
    }

    public static String mset(List<Map<String, String>> mapList) {
        String mset;
        try (Jedis jedis = SysJedisPool.getResource()) {
            String[] keysvalues = ConvertUtils.listMap2Array(mapList);
            mset = jedis.mset(keysvalues);
        }
        return mset;
    }

    public static long msetnx(String... keysvalues) {
        long msetnx;
        try (Jedis jedis = SysJedisPool.getResource()) {
            msetnx = jedis.msetnx(keysvalues);
        }
        return msetnx;
    }

    public static long msetnx(List<Map<String, String>> mapList) {
        long msetnx;
        try (Jedis jedis = SysJedisPool.getResource()) {
            String[] keysvalues = ConvertUtils.listMap2Array(mapList);
            msetnx = jedis.msetnx(keysvalues);
        }
        return msetnx;
    }

    public static long incr(String key) {
        long incr;
        try (Jedis jedis = SysJedisPool.getResource()) {
            incr = jedis.incr(key);
        }
        return incr;
    }

    public static long incrBy(String key, long increment) {
        long incrBy;
        try (Jedis jedis = SysJedisPool.getResource()) {
            incrBy = jedis.incrBy(key, increment);
        }
        return incrBy;
    }

    public static double incrByFloat(String key, double increment) {
        double incrByFloat;
        try (Jedis jedis = SysJedisPool.getResource()) {
            incrByFloat = jedis.incrByFloat(key, increment);
        }
        return incrByFloat;
    }

    public static long decr(String key) {
        long decr;
        try (Jedis jedis = SysJedisPool.getResource()) {
            decr = jedis.decr(key);
        }
        return decr;
    }

    public static long decrBy(String key, long decrement) {
        long decrBy;
        try (Jedis jedis = SysJedisPool.getResource()) {
            decrBy = jedis.decrBy(key, decrement);
        }
        return decrBy;
    }

    public static long append(String key, String value) {
        long append;
        try (Jedis jedis = SysJedisPool.getResource()) {
            append = jedis.append(key, value);
        }
        return append;
    }

    public static String substr(String key, int start, int end) {
        String substr;
        try (Jedis jedis = SysJedisPool.getResource()) {
            substr = jedis.substr(key, start, end);
        }
        return substr;
    }

    public static long strlen(String key) {
        long strlen;
        try (Jedis jedis = SysJedisPool.getResource()) {
            strlen = jedis.strlen(key);
        }
        return strlen;
    }

    /**
     * 计算给定字符串中，被设置为 1 的比特位的数量。
     * 一般情况下，给定的整个字符串都会被进行计数，通过指定额外的 start 或 end 参数，可以让计数只在特定的位上进行。
     * start 和 end 参数的设置和 GETRANGE 命令类似，都可以使用负数值，比如：-1 表示最后一个位，-2 表示倒数第二个位，以此类推。
     * 不存在的 key 被当成是空字符串来处理，因此对一个不存在的 key 进行 BITCOUNT 操作，结果为 0 。
     *
     * @param key
     * @return long
     */
    public static long bitcount(String key) {
        long bitcount;
        try (Jedis jedis = SysJedisPool.getResource()) {
            bitcount = jedis.bitcount(key);
        }
        return bitcount;
    }

    public static long bitcount(String key, long start, long end) {
        long bitcount;
        try (Jedis jedis = SysJedisPool.getResource()) {
            bitcount = jedis.bitcount(key, start, end);
        }
        return bitcount;
    }

    public static long bitcount(String key, long start, long end, BitCountOption option) {
        long bitcount;
        try (Jedis jedis = SysJedisPool.getResource()) {
            // TODO
            bitcount = jedis.bitcount(key, start, end, option);
        }
        return bitcount;
    }

    /**
     * 返回字符串里面第一个被设置为 1 或 0 的 bit 位。
     * 默认情况下整个字符串都会被检索一次，只有在指定 start 和 end 参数，该范围被解释为一个字节的范围，而不是一系列的位。所以 start=0 并且 end=2 是指前三个字节范围内查找。
     * 注意，返回的位的位置始终是从 0 开始的，即使使用了 start 来指定了一个开始字节也是这样。
     * 和 GETRANGE 命令一样，start 和 end 也可以包含负值，负值将从字符串的末尾开始计算，-1 是字符串的最后一个字节，-2 是倒数第二个，以此类推。
     * 不存在的 key 将会被当做空字符串来处理。
     *
     * @param key
     * @param value
     * @return long
     */
    public static long bitpos(String key, boolean value) {
        long bitpos;
        try (Jedis jedis = SysJedisPool.getResource()) {
            bitpos = jedis.bitpos(key, value);
        }
        return bitpos;
    }

    public static long bitpos(String key, boolean value, BitPosParams params) {
        long bitpos;
        try (Jedis jedis = SysJedisPool.getResource()) {
            // TODO
            bitpos = jedis.bitpos(key, value, params);
        }
        return bitpos;
    }

    /**
     * 该命令语法格式：BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]
     *
     * @param key
     * @param arguments
     * @return java.util.List<java.lang.Long>
     */
    public static List<Long> bitfield(String key, String... arguments) {
        List<Long> bitfield = Lists.newArrayList();
        try (Jedis jedis = SysJedisPool.getResource()) {
            // TODO
            bitfield = jedis.bitfield(key, arguments);
        }
        return bitfield;
    }

    public static List<Long> bitfieldReadonly(String key, String... arguments) {
        List<Long> bitfieldReadonly = Lists.newArrayList();
        try (Jedis jedis = SysJedisPool.getResource()) {
            // TODO
            bitfieldReadonly = jedis.bitfieldReadonly(key, arguments);
        }
        return bitfieldReadonly;
    }

    public static long bitop(BitOP op, String destKey, String... srcKeys) {
        long bitop;
        try (Jedis jedis = SysJedisPool.getResource()) {
            // TODO
            bitop = jedis.bitop(op, destKey, srcKeys);
        }
        return bitop;
    }

    /**
     * 计算 keyA 和 keyB 的最长公共子序列
     *
     * @param keyA
     * @param keyB
     * @param params
     * @return redis.clients.jedis.resps.LCSMatchResult
     */
    public static LCSMatchResult strAlgoLCSKeys(String keyA, String keyB, LCSParams params) {
        LCSMatchResult strAlgoLCSKeys;
        try (Jedis jedis = SysJedisPool.getResource()) {
            // TODO
            strAlgoLCSKeys = jedis.lcs(keyA, keyB, params);
        }
        return strAlgoLCSKeys;
    }

    /*public static void main(String[] args) {
        SetParams params1 = SetParams.setParams();
        System.out.println("set：" + set("key1", "value1", params1));

        SetParams params2 = SetParams.setParams();
        params2.ex(3L);// 设置指定的过期时间，以秒为单位
        // params2.px(3L);// 设置指定的过期时间，以毫秒为单位
        // params2.exAt(3L);// 设置 key 到期的指定 Unix 时间，以秒为单位
        // params2.pxAt(3L);// 设置 key 到期的指定 Unix 时间，以毫秒为单位
        System.out.println("set：" + set("key2", "value2", params2));

        SetParams params3 = SetParams.setParams();
        params3.xx();// 仅当 key 已存在时才设置它
        params3.nx();// 仅当 key 不存在时才设置它
        System.out.println("set：" + set("key3", "value3", params3));

        SetParams params4 = SetParams.setParams();
        //params4.get();// 返回存储在 key 中的旧值，或者当 key 不存在时返回 null
        System.out.println("set：" + set("key4", "value4", params4));
    }*/
}
